package com.zn.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.zn.entity.*;
import com.zn.feignClient.HomePageCallbackClient;
import com.zn.feignClient.PayCallbackClient;
import com.zn.mapper.*;
import com.zn.service.AppCustomerService;
import com.zn.util.*;
import com.zn.vo.Message;
import com.zn.web.dto.AppCustomerDto;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * Created by yinjiawei on 2018/7/9.
 */
@Service
public class AppCustomerServiceImpl implements AppCustomerService {
    private static final Logger LOGGER = LoggerFactory.getLogger(AppCustomerServiceImpl.class);
    /**阿里云短信参数**/
    @Value("${aliyun.sms.accessKeyId}")
    private String accessKeyId;
    @Value("${aliyun.sms.accessKeySecret}")
    private String accessKeySecret;
    @Value("${aliyun.sms.template.open-account-notify-code}")
    private String ACCOUNT_NOTIFY_TEMPLATE_CODE;
    @Value("${aliyun.sms.template.retrieve-account-notify-code}")
    private String RETRIEVE_ACCOUNT_NOTIFY_CODE;
    @Value("${aliyun.sms.signName}")
    private String signName;
    /**实名认证参数**/
    @Value("${validate.host}")
    private String validateHost;
    @Value("${validate.path}")
    private String validatePath;
    @Value("${validate.appcode}")
    private String validateAppcode;
    @Value("${validate.method}")
    private String validateMethod;
    @Autowired
    private AppCustomerMapper appCustomerMapper;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private PayCallbackClient payCallbackClient;
    @Autowired
    private CustomerCardInfoMapper customerCardInfoMapper;
    @Autowired
    private AgencyBusinessMapper agencyBusinessMapper;
    @Autowired
    private HomePageCallbackClient homePageCallbackClient;

    @Override
    public ResponseEntity<Message> customerRegister(AppCustomerDto appCustomerDto) {
        try {
            AppCustomer appCustomer=new AppCustomer();
            appCustomer.setCustomerId(UUIDUtils.getUuid());
            appCustomer.setBusinessId(appCustomerDto.getBusinessId());
            appCustomer.setCustomerTel(appCustomerDto.getCustomerTel());
            AgencyBusiness isExist=agencyBusinessMapper.selectByBusinessInviteCode(Integer.valueOf(appCustomerDto.getBusinessInviteCode()));
            //如果代理商邀请码不存在则提示
            if(isExist==null){
                return ResponseEntity.ok(Message.AGENCY_BUSINESS_CODE_IS_NULL);
            }
            //获取客户自增号
            Long customerIncrNum=getCustomerIncrNum(appCustomerDto.getBusinessInviteCode());
            //客户交易账号=一级代理唯一识别号+邀请码+客户自增号
            String customerTradeAccount=isExist.getUniqueIdentification()+appCustomerDto.getBusinessInviteCode()+customerIncrNum;
            appCustomer.setCustomerTradeAccount(customerTradeAccount);
            appCustomer.setCreateTime(new Date());
            //交易密码=MD5(交易账户+交易密码)
            appCustomer.setCustomerTradePassword(EnDecryptUtil.MD5(customerTradeAccount+appCustomerDto.getCustomerTradePassword()));
            boolean flag=appCustomerMapper.insertSelective(appCustomer)>0;
            if(flag){
                //注册成功 重新查询用户信息
                appCustomer=appCustomerMapper.customerLogin(appCustomer);
                //注册成功 短信告知用户账户
                this.registerSuccessSms(appCustomerDto.getCustomerTel(),customerTradeAccount,ACCOUNT_NOTIFY_TEMPLATE_CODE);
                //登录成功 生成token保存到redis 24小时有效期
                String tokenKey=Constant.CUSTOMER_TOKEN_BEFROM+appCustomer.getCustomerTel();
                String token=UUIDUtils.getUuid();
                redisTemplate.opsForValue().set(tokenKey, token);
                //设置24小时失效
                redisTemplate.expire(tokenKey, 24, TimeUnit.HOURS);
                appCustomer.setAccessToken(token);
                this.feignCustomerKnownAgreement(appCustomer.getCustomerId(),appCustomerDto.getAgreementId());
                return ResponseEntity.ok(Message.successData(appCustomer));
            }else{
                return ResponseEntity.ok(Message.REGISTER_ERROR);
            }
        }catch (Exception e){
            e.printStackTrace();
            return ResponseEntity.ok(Message.SYS_ERROR);
        }
    }

    private void feignCustomerKnownAgreement(String customerId,String agreementId){
        try {
            /**注册成功并知晓开户协议**/
            JSONObject jsonObject=new JSONObject();
            jsonObject.put("customerId",customerId);
            jsonObject.put("agreementId",agreementId);
            ResponseEntity<Message> responseEntity=homePageCallbackClient.customerKnownAgreement(jsonObject);
            if(responseEntity!=null){
                LOGGER.info("customerRegister customerKnownAgreement------->"+responseEntity.getStatusCode());
            }
        }catch (Exception e){
            LOGGER.error("feignCustomerKnownAgreement error------>",e);
        }

    }

    @Override
    public ResponseEntity<Message> retrieveAccount(AppCustomerDto appCustomerDto) {
        try {
            AppCustomer appCustomer=appCustomerMapper.selectByCustomerTel(appCustomerDto.getCustomerTel());
            if(appCustomer!=null){
                this.registerSuccessSms(appCustomer.getCustomerTel(), appCustomer.getCustomerTradeAccount(),RETRIEVE_ACCOUNT_NOTIFY_CODE);
            }
            return ResponseEntity.ok(Message.REQ_SUCCESS);
        }catch (Exception e){
            e.printStackTrace();
            return ResponseEntity.ok(Message.SYS_ERROR);
        }
    }

    @Async("executorPool")
    @Override
    public void registerSuccessSms(String customerTel,String tradeAccount,String smsTemplate){
        try {
            Map map = new HashMap();
            map.put("code", tradeAccount);//map里面装有yes
            String jsonObject = JSONObject.toJSONString(map);
            SendSmsResponse sendSmsResponse= SmsUtils.sendSms(accessKeyId,accessKeySecret,customerTel,smsTemplate,jsonObject,signName);
            LOGGER.info("sendSmsResponse:" + sendSmsResponse.toString());
            if(!"OK".equals(sendSmsResponse.getCode())){
                LOGGER.error("用户：" + customerTel + "注册成功，短信发送失败.........." + sendSmsResponse.getMessage());
            }
        }catch (Exception e){
            LOGGER.error("用户："+customerTel+"注册成功，发短信程序异常..........",e);
        }
    }

    @Override
    public AppCustomer selectByCustomerTel(String customerTel) {
        return appCustomerMapper.selectByCustomerTel(customerTel);
    }

    @Override
    public ResponseEntity<Message> customerLogin(AppCustomerDto appCustomerDto) {
        String md5Password=EnDecryptUtil.MD5(appCustomerDto.getCustomerTradeAccount() + appCustomerDto.getCustomerTradePassword());
        AppCustomer parameterObj=new AppCustomer();
        parameterObj.setCustomerTradeAccount(appCustomerDto.getCustomerTradeAccount());
        parameterObj.setCustomerTradePassword(md5Password);
        AppCustomer appCustomer=appCustomerMapper.customerLogin(parameterObj);
        if(appCustomer==null){
            //账号密码不匹配
            return ResponseEntity.ok(Message.ACCOUNT_PASSWORD_MISMATCH);
        }
        //用户被禁用
        if(appCustomer.getDisableStatus()==1){
            return ResponseEntity.ok(Message.CUSTOMER_ALREADY_DISABLE);
        }
        //登录成功 生成token保存到redis 24小时有效期
        String tokenKey=Constant.CUSTOMER_TOKEN_BEFROM+appCustomer.getCustomerTel();
        String token=UUIDUtils.getUuid();
        redisTemplate.opsForValue().set(tokenKey, token);
        //设置24小时失效
        redisTemplate.expire(tokenKey, 24, TimeUnit.HOURS);
        appCustomer.setAccessToken(token);
        return ResponseEntity.ok(Message.successData(appCustomer));
    }

    /**
     * 修改账户的密码
     * @param appCustomerDto
     * @return
     */
    @Override
    public ResponseEntity<Message> updateCustomerPassword(AppCustomerDto appCustomerDto) {
        /**修改交易密码**/
        if(appCustomerDto.getUpdatePasswordType()==1){
            //校验参数
            if(StringUtils.isBlank(appCustomerDto.getCustomerTradeAccount()) || StringUtils.isBlank(appCustomerDto.getCustomerTradePassword())
                    || StringUtils.isBlank(appCustomerDto.getNewCustomerTradePassword()) || StringUtils.isBlank(appCustomerDto.getConfirmCustomerTradePassword())){
                return ResponseEntity.ok(Message.ARGS_ERROR);
            }
            /**正则密码交易密码必须6-24位,数字+字母组合**/
            if(!appCustomerDto.getNewCustomerTradePassword().matches(Constant.TRADE_PASSWORD_REGEX)){
                return ResponseEntity.ok(Message.TRADE_PASSWORD_REGEX_ERROR);
            }
            if(!appCustomerDto.getNewCustomerTradePassword().equals(appCustomerDto.getConfirmCustomerTradePassword())){
                /**确认密码不一致**/
                return ResponseEntity.ok(Message.CONFIRM_PASSWORD_ATYPISM);
            }
            //交易密码=MD5(交易账户+交易密码)
            String md5Password=EnDecryptUtil.MD5(appCustomerDto.getCustomerTradeAccount() + appCustomerDto.getCustomerTradePassword());
            AppCustomer parameterObj=new AppCustomer();
            parameterObj.setCustomerTradeAccount(appCustomerDto.getCustomerTradeAccount());
            parameterObj.setCustomerTradePassword(md5Password);
            AppCustomer appCustomer=appCustomerMapper.customerLogin(parameterObj);
            if(appCustomer==null){
//                Message message=Message.ACCOUNT_PASSWORD_MISMATCH;
//                message.setMsg("原密码不正确");
                /**账号与密码不匹配**/
                return ResponseEntity.ok(Message.OLD_PASSWORD_INCORRECT);
            }
            String newMd5Password=EnDecryptUtil.MD5(appCustomerDto.getCustomerTradeAccount() + appCustomerDto.getConfirmCustomerTradePassword());
            /**覆盖掉查询设置的**/
            parameterObj.setCustomerTradePassword(newMd5Password);
            parameterObj.setCustomerId(appCustomer.getCustomerId());
            appCustomerMapper.updateByPrimaryKeySelective(parameterObj);
            //把token清掉
            redisTemplate.delete(Constant.CUSTOMER_TOKEN_BEFROM + appCustomer.getCustomerTel());
            return ResponseEntity.ok(Message.REQ_SUCCESS);
        }
        else if(appCustomerDto.getUpdatePasswordType()==2){
            //校验参数
            if(StringUtils.isBlank(appCustomerDto.getCustomerTradeAccount()) || StringUtils.isBlank(appCustomerDto.getCustomerCapitalPassword())
                    || StringUtils.isBlank(appCustomerDto.getNewCustomerCapitalPassword()) || StringUtils.isBlank(appCustomerDto.getConfirmCustomerCapitalPassword())){
                return ResponseEntity.ok(Message.ARGS_ERROR);
            }
            if(!appCustomerDto.getNewCustomerCapitalPassword().equals(appCustomerDto.getConfirmCustomerCapitalPassword())){
                /**确认密码不一致**/
                return ResponseEntity.ok(Message.CONFIRM_PASSWORD_ATYPISM);
            }
            //资金密码=MD5(交易账户+资金密码)
            String md5Password=EnDecryptUtil.MD5(appCustomerDto.getCustomerTradeAccount() + appCustomerDto.getCustomerCapitalPassword());
            AppCustomer parameterObj=new AppCustomer();
            parameterObj.setCustomerTradeAccount(appCustomerDto.getCustomerTradeAccount());
            parameterObj.setCustomerCapitalPassword(md5Password);
            AppCustomer appCustomer=appCustomerMapper.customerLogin(parameterObj);
            if(appCustomer==null){
//                Message message=Message.ACCOUNT_PASSWORD_MISMATCH;
//                message.setMsg("原密码不正确");
                /**账号与密码不匹配**/
                return ResponseEntity.ok(Message.OLD_PASSWORD_INCORRECT);
            }
            String newMd5Password=EnDecryptUtil.MD5(appCustomerDto.getCustomerTradeAccount() + appCustomerDto.getNewCustomerCapitalPassword());
            /**覆盖上面set的值**/
            parameterObj.setCustomerCapitalPassword(newMd5Password);
            parameterObj.setCustomerId(appCustomer.getCustomerId());
            appCustomerMapper.updateByPrimaryKeySelective(parameterObj);
            return ResponseEntity.ok(Message.REQ_SUCCESS);
        }
        return ResponseEntity.ok(Message.SYS_ERROR);
    }
    /**
     * 客户初始设置资金密码
     * @param appCustomerDto
     * @return
     */
    @Override
    public ResponseEntity<Message> initCustomerCapitalPassword(AppCustomerDto appCustomerDto) {
        AppCustomer appCustomer=appCustomerMapper.selectByPrimaryKey(appCustomerDto.getCustomerId());
        if(appCustomer==null){
            /**用户不存在**/
            return ResponseEntity.ok(Message.CUSTOMER_NOT_EXIST);
        }
        AppCustomer parameterObj=new AppCustomer();
        parameterObj.setCustomerId(appCustomer.getCustomerId());
        //资金密码=MD5(交易账户+资金密码)
        String md5Password=EnDecryptUtil.MD5(appCustomer.getCustomerTradeAccount() + appCustomerDto.getCustomerCapitalPassword());
        parameterObj.setCustomerCapitalPassword(md5Password);
        appCustomerMapper.updateByPrimaryKeySelective(parameterObj);
        return ResponseEntity.ok(Message.REQ_SUCCESS);
    }

    @Override
    public ResponseEntity<Message> checkCustomerCapitalPassword(AppCustomerDto appCustomerDto) {
        return null;
    }

    @Override
    public AppCustomer getCustomerInfo(String customerId) {
        AppCustomer appCustomer=appCustomerMapper.selectByPrimaryKey(customerId);
        this.dfQueryByCustomerf(customerId);
        return appCustomer;
    }

    @Override
    public ResponseEntity<Message> certification(String idCardFront, String idCardReverse, String idCard, String name,String customerId)throws Exception{
        AppCustomer appCustomer=appCustomerMapper.selectByPrimaryKey(customerId);
        if(appCustomer==null){
            return ResponseEntity.ok(Message.ARGS_ERROR);
        }
        CustomerCardInfo acCustomerCardInfo=customerCardInfoMapper.selectByCustomerId(customerId);
        if(acCustomerCardInfo!=null){
            /**客户已认证**/
            return ResponseEntity.ok(Message.CUSTOMER_ALREADY_AUTHENTICATION);
        }
        String responseStr=IdCardValidate.validate(idCard, name,validateHost,validatePath,validateAppcode,validateMethod);
        JSONObject json = JSONObject.parseObject(responseStr);
        String status=json.get("status").toString();
        String msg=json.get("msg").toString();
//        String idCard=json.get("idCard").toString();
//        String name=json.get("name").toString();
        if(!"01".equals(status)){
//            appCustomer.setAuthenticationStatus(2);
            appCustomer.setAuthenticationMsg(msg);
            appCustomerMapper.updateByPrimaryKeySelective(appCustomer);
            Message message=new Message("534",msg);
            return ResponseEntity.ok(message);
        }
        appCustomer.setAuthenticationStatus(1);
        appCustomer.setAuthenticationMsg(msg);
        appCustomerMapper.updateByPrimaryKeySelective(appCustomer);
        String sex=json.get("sex").toString();
        String area=json.get("area").toString();
        String province=json.get("province").toString();
        String city=json.get("city").toString();
        String prefecture=json.get("prefecture").toString();
        String birthday=json.get("birthday").toString();
        String addrCode=json.get("addrCode").toString();
        String lastCode=json.get("lastCode").toString();
        CustomerCardInfo customerCardInfo=new CustomerCardInfo();
        customerCardInfo.setCustomerCardId(UUIDUtils.getUuid());
        customerCardInfo.setCustomerId(appCustomer.getCustomerId());
        customerCardInfo.setSex(sex);
        customerCardInfo.setArea(area);
        customerCardInfo.setProvince(province);
        customerCardInfo.setCity(city);
        customerCardInfo.setPrefecture(prefecture);
        customerCardInfo.setBirthday(birthday);
        customerCardInfo.setAddrcode(addrCode);
        customerCardInfo.setLastcode(lastCode);
        customerCardInfo.setIdCardFront(idCardFront);
        customerCardInfo.setIdCardReverse(idCardReverse);
        customerCardInfo.setName(name);
        customerCardInfo.setIdCard(idCard);
        customerCardInfoMapper.insertSelective(customerCardInfo);
        Message message=new Message("200",msg);
        return ResponseEntity.ok(message);
    }

    /**
     * 用户重置密码
     * @param appCustomerDto
     * @return
     */
    @Override
    public ResponseEntity<Message> resetCustomerPassword(AppCustomerDto appCustomerDto) {
        /**修改交易密码**/
        if(appCustomerDto.getUpdatePasswordType()==1){
            //校验参数
            if(StringUtils.isBlank(appCustomerDto.getNewCustomerTradePassword())
                    || StringUtils.isBlank(appCustomerDto.getConfirmCustomerTradePassword())){
                return ResponseEntity.ok(Message.ARGS_ERROR);
            }
            /**正则密码交易密码必须6-24位,数字+字母组合**/
            if(!appCustomerDto.getNewCustomerTradePassword().matches(Constant.TRADE_PASSWORD_REGEX)){
                return ResponseEntity.ok(Message.TRADE_PASSWORD_REGEX_ERROR);
            }
            if(!appCustomerDto.getNewCustomerTradePassword().equals(appCustomerDto.getConfirmCustomerTradePassword())){
                /**确认密码不一致**/
                return ResponseEntity.ok(Message.CONFIRM_PASSWORD_ATYPISM);
            }
            AppCustomer appCustomer=appCustomerMapper.selectByCustomerTel(appCustomerDto.getCustomerTel());
            if(appCustomer==null){
                /**该手机号未注册**/
                return ResponseEntity.ok(Message.PHONE_NOT_REGISTER);
            }
            AppCustomer parameterObj=new AppCustomer();
            //交易密码=MD5(交易账户+交易密码)
            String newMd5Password=EnDecryptUtil.MD5(appCustomer.getCustomerTradeAccount() + appCustomerDto.getConfirmCustomerTradePassword());
            /**覆盖掉查询设置的**/
            parameterObj.setCustomerTradePassword(newMd5Password);
            parameterObj.setCustomerId(appCustomer.getCustomerId());
            appCustomerMapper.updateByPrimaryKeySelective(parameterObj);
            return ResponseEntity.ok(Message.REQ_SUCCESS);
        }
        /**修改资金密码**/
        else if(appCustomerDto.getUpdatePasswordType()==2){
            //校验参数
            if(StringUtils.isBlank(appCustomerDto.getNewCustomerCapitalPassword()) || StringUtils.isBlank(appCustomerDto.getConfirmCustomerCapitalPassword())){
                return ResponseEntity.ok(Message.ARGS_ERROR);
            }
            if(!appCustomerDto.getNewCustomerCapitalPassword().equals(appCustomerDto.getConfirmCustomerCapitalPassword())){
                /**确认密码不一致**/
                return ResponseEntity.ok(Message.CONFIRM_PASSWORD_ATYPISM);
            }
            //资金密码=MD5(交易账户+资金密码)
            AppCustomer parameterObj=new AppCustomer();
            AppCustomer appCustomer=appCustomerMapper.selectByCustomerTel(appCustomerDto.getCustomerTel());
            if(appCustomer==null){
                /**该手机号未注册**/
                return ResponseEntity.ok(Message.PHONE_NOT_REGISTER);
            }
            String newMd5Password=EnDecryptUtil.MD5(appCustomer.getCustomerTradeAccount() + appCustomerDto.getNewCustomerCapitalPassword());
            /**覆盖上面set的值**/
            parameterObj.setCustomerCapitalPassword(newMd5Password);
            parameterObj.setCustomerId(appCustomer.getCustomerId());
            appCustomerMapper.updateByPrimaryKeySelective(parameterObj);
            return ResponseEntity.ok(Message.REQ_SUCCESS);
        }
        return ResponseEntity.ok(Message.SYS_ERROR);
    }

    private Long getCustomerIncrNum(String businessInviteCode){
        String customerIncrNumStr=redisTemplate.opsForValue().get(Constant.CUSTOMER_INCR_NUM+businessInviteCode);
        //如果Key不存在
        if(StringUtils.isBlank(customerIncrNumStr)){
            //给Key设置值 客户自增id从1001开始自增
            redisTemplate.opsForValue().set(Constant.CUSTOMER_INCR_NUM+businessInviteCode, "1000");
        }
        Long customerIncrNum=redisTemplate.opsForValue().increment(Constant.CUSTOMER_INCR_NUM+businessInviteCode,1);
        return customerIncrNum;
    }

    @Async("executorPool")
    @Override
    public void dfQueryByCustomerf(String customerId){
        try{
            payCallbackClient.dfQueryByCustomer(customerId);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
